package com.travel.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.travel.common.UserContext;
import com.travel.entity.dto.AiRequestParam;
import com.travel.entity.dto.ChatMessageDTO;
import com.travel.entity.po.User;
import com.travel.entity.vo.ChatResponseVO;
import com.travel.exception.BusinessException;
import com.travel.mapper.UserMapper;
import com.travel.service.ChatService;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicHeader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 聊天服务实现类
 */
@Service
@Slf4j
public class ChatServiceImpl implements ChatService {

    private final String API_KEY = "app-NpdVYOneXqpqSuW2Nov7AI5q";
    private final String API_URL = "https://api.dify.ai/v1/chat-messages";
    // 流式和非流式API地址是相同的，通过response_mode参数区分
    private final String STREAM_API_URL = "https://api.dify.ai/v1/chat-messages";
    private final BasicHeader AUTH_HEADER = new BasicHeader("Authorization", "Bearer " + API_KEY);
    
    // 线程池用于异步处理流式响应
    private final ExecutorService executorService = Executors.newCachedThreadPool();

    @Autowired
    UserMapper userMapper;

    @Override
    public String sendMessage(ChatMessageDTO chatMessage) {
        // 从UserContext获取用户ID
        Long userId = UserContext.getUserId();
        if (userId == null) {
            throw new BusinessException("用户未登录，请先登录");
        }
        
        // 获取用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        log.info("用户[{}]发送聊天消息: {}", user.getUsername(), chatMessage.getMessage());
        
        // 构建请求参数
        Map<String, String> inputs = new HashMap<>();
        inputs.put("message", chatMessage.getMessage());
        
        AiRequestParam requestBody = AiRequestParam.builder()
                .user(user.getUsername())
                .inputs(inputs)
                .query(chatMessage.getMessage())
                .response_mode("streaming") // 使用流式响应模式
                .build();
        
        // 如果有会话ID，且格式正确，添加到请求参数
        if (StringUtils.hasText(chatMessage.getSessionId()) && isValidUUID(chatMessage.getSessionId())) {
            requestBody.setConversation_id(chatMessage.getSessionId());
        }
        
        try (CloseableHttpClient httpClient = HttpClients.custom().build()) {
            // 构建POST请求 - 使用流式API
            HttpPost httpPost = new HttpPost(STREAM_API_URL);
            httpPost.setHeader(AUTH_HEADER);
            httpPost.setHeader("Content-type", "application/json");
            httpPost.setHeader("Accept", "text/event-stream");  // 流式响应
            
            String jsonBody = JSONObject.toJSONString(requestBody);
            log.debug("流式请求体: {}", jsonBody);
            StringEntity entity = new StringEntity(jsonBody, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            
            // 执行请求
            CloseableHttpResponse response = httpClient.execute(httpPost);
            log.info("流式响应状态: {}", response.getCode());
            
            // 处理流式响应，但同步等待完整结果
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(response.getEntity().getContent()))) {

                log.info("开始读取流式响应...");
                String line;
                StringBuilder messageBuilder = new StringBuilder();
                String conversationId = null;
                String messageId = null;
                
                while ((line = reader.readLine()) != null) {
                    // 忽略空行
                    if (line.isEmpty()) {
                        continue;
                    }
                    
                    log.debug("读取流式数据行: {}", line);
                    
                    // SSE数据行以"data:"开头
                    if (line.startsWith("data:")) {
                        String jsonData = line.substring(5).trim();
                        
                        // 检查是否为[DONE]标记，表示流结束
                        if ("[DONE]".equals(jsonData)) {
                            log.info("流结束标记[DONE]");
                            break;
                        }
                        
                        try {
                            JSONObject chunk = JSONObject.parseObject(jsonData);
                            log.debug("解析JSON数据: {}", chunk);
                            
                            // 提取会话ID和消息ID（仅在第一个块中）
                            if (conversationId == null) {
                                conversationId = chunk.getString("conversation_id");
                                log.info("获取会话ID: {}", conversationId);
                            }
                            
                            if (messageId == null) {
                                messageId = chunk.getString("id");
                                log.info("获取消息ID: {}", messageId);
                            }
                            
                            // 获取当前块的文本内容
                            String chunkText = chunk.getString("answer");
                            if (chunkText != null) {
                                messageBuilder.append(chunkText);
                                log.debug("收到文本块: {}", chunkText);
                            }
                        } catch (Exception e) {
                            log.error("解析流式响应数据失败: {}", jsonData, e);
                        }
                    }
                }
                
                // 处理AI响应文本，截取最后一个"</think>"后面的内容
                String processedText = processAiResponseText(messageBuilder.toString());
                // 确保在流处理结束时打印完整响应内容
                log.info("AI完整响应内容: {}", processedText);
                log.info("流式响应读取完成");
                
                return processedText != null ? processedText : "AI未返回有效内容";
                
            } catch (Exception e) {
                log.error("处理流式响应失败", e);
                return "处理AI响应失败，请稍后再试";
            }
        } catch (IOException e) {
            log.error("调用AI API失败", e);
            return "AI服务暂时不可用，请稍后再试";
        }
    }

    @Override
    public SseEmitter sendMessageStream(ChatMessageDTO chatMessage) {
        // 创建一个超时为30分钟的SSE发射器
        SseEmitter emitter = new SseEmitter(1800000L);

        // 从UserContext获取用户ID
        Long userId = UserContext.getUserId();
        if (userId == null) {
            throw new BusinessException("用户未登录，请先登录");
        }

        // 获取用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        log.info("用户[{}]发送流式聊天消息: {}", user.getUsername(), chatMessage.getMessage());

        // 异步处理流式响应
        executorService.execute(() -> {
            try {
                // 构建请求参数
                Map<String, String> inputs = new HashMap<>();
//                inputs.put("message", chatMessage.getMessage());
                log.info("构建请求参数: {}", inputs);

                AiRequestParam requestBody = AiRequestParam.builder()
                        .user(user.getUsername())
                        .inputs(inputs)
                        .query(chatMessage.getMessage())
                        .response_mode("streaming") // 设置为流式响应模式
                        .build();

                // 如果有会话ID，添加到请求参数
                if (StringUtils.hasText(chatMessage.getSessionId())) {
                    requestBody.setConversation_id(chatMessage.getSessionId());
                }

                CloseableHttpClient httpClient = HttpClients.custom().build();
                HttpPost httpPost = new HttpPost(STREAM_API_URL);
                httpPost.setHeader(AUTH_HEADER);
                httpPost.setHeader("Content-type", "application/json");
                httpPost.setHeader("Accept", "text/event-stream");

                String jsonBody = JSONObject.toJSONString(requestBody);
                StringEntity entity = new StringEntity(jsonBody, ContentType.APPLICATION_JSON);
                httpPost.setEntity(entity);

                log.info("发送流式请求: {}", STREAM_API_URL);
                log.info("流式请求体: {}", jsonBody);
                // 执行请求
                CloseableHttpResponse response = httpClient.execute(httpPost);
                log.info("流式响应状态: {}", response.getCode());
                // 处理流式响应
                try (BufferedReader reader = new BufferedReader(
                        new InputStreamReader(response.getEntity().getContent()))) {

                    log.info("开始读取流式响应...");
                    String line;
                    StringBuilder messageBuilder = new StringBuilder();
                    String conversationId = null;
                    String messageId = null;

                    while ((line = reader.readLine()) != null) {
                        // 忽略空行
                        if (line.isEmpty()) {
                            continue;
                        }

                        log.debug("读取流式数据行: {}", line);

                        // SSE数据行以"data:"开头
                        if (line.startsWith("data:")) {
                            String jsonData = line.substring(5).trim();

                            // 检查是否为[DONE]标记，表示流结束
                            if ("[DONE]".equals(jsonData)) {
                                log.info("流结束标记[DONE]");
                                // 处理AI响应文本，截取最后一个"</think>"后面的内容
                                String processedText = processAiResponseText(messageBuilder.toString());
                                // 打印完整的响应内容汇总
                                log.info("AI完整响应内容: {}", processedText);
                                // 发送最后一个消息块，标记为结束
                                ChatResponseVO finalResponse = ChatResponseVO.builder()
                                        .message(processedText)
                                        .sessionId(conversationId)
                                        .messageId(messageId)
                                        .success(true)
                                        .isStreaming(true)
                                        .isLastChunk(true)
                                        .build();

                                emitter.send(finalResponse);
                                break;
                            }

                            try {
                                JSONObject chunk = JSONObject.parseObject(jsonData);
                                log.debug("解析JSON数据: {}", chunk);

                                // 提取会话ID和消息ID（仅在第一个块中）
                                if (conversationId == null) {
                                    conversationId = chunk.getString("conversation_id");
                                    log.info("获取会话ID: {}", conversationId);
                                }

                                if (messageId == null) {
                                    messageId = chunk.getString("id");
                                    log.info("获取消息ID: {}", messageId);
                                }

                                // 获取当前块的文本内容
                                String chunkText = chunk.getString("answer");
                                if (chunkText != null) {
                                    messageBuilder.append(chunkText);
                                    log.debug("收到文本块: {}", chunkText);

                                    // 创建消息块响应
                                    ChatResponseVO chunkResponse = ChatResponseVO.builder()
                                            .message(chunkText)
                                            .sessionId(conversationId)
                                            .messageId(messageId)
                                            .chunkId(UUID.randomUUID().toString())
                                            .success(true)
                                            .isStreaming(true)
                                            .isLastChunk(false)
                                            .build();

                                    // 发送消息块给客户端
                                    emitter.send(chunkResponse);
                                    log.debug("发送消息块到客户端");
                                }
                            } catch (Exception e) {
                                log.error("解析流式响应数据失败: {}", jsonData, e);
                            }
                        }
                    }
                    // 处理AI响应文本，截取最后一个"</think>"后面的内容
                    String processedText = processAiResponseText(messageBuilder.toString());
                    // 确保在流处理结束时打印完整响应内容
                    log.info("AI完整响应内容: {}", processedText);
                    log.info("流式响应读取完成");
                    // 完成处理
                    emitter.complete();

                } catch (Exception e) {
                    log.error("处理流式响应失败", e);
                    emitter.completeWithError(e);
                } finally {
                    try {
                        httpClient.close();
                    } catch (IOException e) {
                        log.error("关闭HTTP客户端失败", e);
                    }
                }
            } catch (Exception e) {
                log.error("流式聊天处理失败", e);
                emitter.completeWithError(e);
            }
        });

        // 设置超时和错误处理
        emitter.onTimeout(() -> log.warn("SSE连接超时"));
        emitter.onError((ex) -> log.error("SSE连接错误: {}", ex.getMessage()));

        return emitter;
    }

    /**
     * 处理AI响应文本，截取最后一个"</think>"后面的内容
     * @param text 原始文本
     * @return 处理后的文本
     */
    private String processAiResponseText(String text) {
        if (text == null || text.isEmpty()) {
            return text;
        }

        int lastThinkEndIndex = text.lastIndexOf("</think>");
        if (lastThinkEndIndex != -1 && lastThinkEndIndex < text.length() - 8) {
            return text.substring(lastThinkEndIndex + 8); // 8是"</think>"的长度
        }

        return text;
    }

    /**
     * 检查字符串是否是有效的UUID格式
     * @param str 要检查的字符串
     * @return 是否是有效UUID
     */
    private boolean isValidUUID(String str) {
        if (str == null) {
            return false;
        }
        try {
            UUID.fromString(str);
            return true;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }
} 